package com.twu.biblioteca;

import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

/**
 * Created by jfulton on 16/01/2014.
 */
public class ItemManager<T extends LibraryItem> {
    private Map<T, Integer> itemToQuantityAvailable = new HashMap<T, Integer>();

    public void addItem(T item, Integer quantity) {
        itemToQuantityAvailable.put(item, quantity);
    }

    public void checkoutItem(String itemTitle) throws ItemUnavailableException {
        T item = findItemByTitle(itemTitle);
        if (!itemAvailable(item)) {
            throw new ItemUnavailableException("Item '" + item.toString() + "' is not available to checkout");
        } else {
            itemToQuantityAvailable.put(item, itemQuantityAvailable(item) - 1);
        }
    }

    public Set<T> getAvailableItems() {
        Set<T> availableItems = new HashSet<T>();
        for (T item : itemToQuantityAvailable.keySet()) {
            if (itemAvailable(item)) {
                availableItems.add(item);
            }
        }

        return availableItems;
    }

    public void returnItem(String itemTitle) throws CannotReturnItemException {
        T item;
        try {

            item = findItemByTitle(itemTitle);
        } catch (ItemUnavailableException e) {
            throw new CannotReturnItemException("Cannot return item titled '" + itemTitle + "'", e);
        }

        itemToQuantityAvailable.put(item, itemQuantityAvailable(item) + 1);
    }

    private boolean itemAvailable(T item) {
        return itemExists(item) && itemQuantityAvailable(item) > 0;
    }

    public T findItemByTitle(String title) throws ItemUnavailableException {
        for (T item : itemToQuantityAvailable.keySet()) {
            if (item.matchesTitle(title)) {
                return item;
            }
        }
        throw new ItemUnavailableException("Item titled '" + title + "' does not exist.");
    }

    private boolean itemExists(T item) {
        return itemToQuantityAvailable.containsKey(item);
    }

    private Integer itemQuantityAvailable(T item) {
        return itemToQuantityAvailable.get(item);
    }
}
